package com.ict.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ict.api.dto.IctRoleDTO;
import com.ict.api.dto.IctUserDTO;
import com.ict.api.entity.IctUser;
import com.ict.api.entity.IctUserRole;
import com.ict.api.vo.IctUserVO;
import com.ict.api.vo.PageResult;
import com.ict.commons.constants.IctConstants;
import com.ict.commons.exception.IctException;
import com.ict.commons.utils.JwtUtils;
import com.ict.mapper.IctUserMapper;
import com.ict.mapper.IctUserRoleMapper;
import com.ict.service.IctRoleService;
import com.ict.service.IctUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户基本信息表 服务实现类
 * </p>
 *
 * @author wjp
 * @since 2025-03-23
 */
@Service
public class IctUserServiceImpl extends ServiceImpl<IctUserMapper, IctUser> implements IctUserService {

    @Resource
    private IctUserMapper userMapper;

    @Resource
    private IctUserRoleMapper userRoleMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Resource
    private IctRoleService roleService;


    @Override
    public void sendCode(String phone) {

    }

    @Override
    public void register(IctUser user) {
        // 查询数据库中是否存在该用户
        LambdaQueryWrapper<IctUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(IctUser::getUsername, user.getUsername());
        IctUser ictUser = userMapper.selectOne(lqw);
        if (ictUser != null) {
            throw new IctException("用户已存在");
        }

        // 加密存储
        String handlePassword = SecureUtil.md5(user.getPassword());
        user.setPassword(handlePassword);
        userMapper.insert(user);
    }

    @Override
    public Map<String, Object> loginVerification(IctUserDTO user) {
        // 根据是否传入验证码，区别走那种登录逻辑
        if (StringUtils.isNotEmpty(user.getCode())) {
            return loginByPhoneCode(user);
        }
        // 账号密码登录
        LambdaQueryWrapper<IctUser> lqw = new LambdaQueryWrapper<>();
        String handlePassword = SecureUtil.md5(user.getPassword());
        lqw.eq(IctUser::getUsername, user.getUsername())
                .eq(IctUser::getPassword, handlePassword);
        IctUser ictUser = userMapper.selectOne(lqw);
        if (ictUser == null) {
            throw new IctException("账号或密码错误");
        }
        String token = JwtUtils.createToken(ictUser.getId(), ictUser.getUsername());

        String tokenKey = IctConstants.PREFIX_TOKEN + token;
        String userStr = JSON.toJSONString(ictUser); //将对象 转为 字符串
        redisTemplate.opsForValue().set(tokenKey, userStr, 1, TimeUnit.DAYS);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        return map;
    }

    /**
     * 手机验证码登录
     *
     * @param user 用户信息
     * @return
     */
    private Map<String, Object> loginByPhoneCode(IctUserDTO user) {
        //        1.根据传来的phone查询redis，是否有验证码
        String phone = user.getPhone();
        String key = IctConstants.PREFIX_CODE + phone;
        String redisCode = redisTemplate.opsForValue().get(key);
        //        2.如果没有值，表示验证码过期，抛出异常
        if (StringUtils.isEmpty(redisCode)) {
            throw new IctException("验证码过期");
        }
        //        3.有值，将前端传来的验证码coed与redis中的验证码比较，不一样则表示验证码输入错误
        if (!redisCode.equals(user.getCode())) {
            throw new IctException("验证码错误");
        }
        //        4.之后根据手机号查询数据库
        LambdaQueryWrapper<IctUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(IctUser::getPhone, user.getPhone());
        IctUser dataUser = userMapper.selectOne(lqw);
        //        5.如果用户不存在，自动注册，新增用户
        boolean isNew = false;
        if (dataUser == null) {
            dataUser = new IctUser();
            dataUser.setPhone(phone);
            //密码加密
            String password = SecureUtil.md5(phone.substring(5));
            dataUser.setPassword(password);
            userMapper.insert(dataUser);
            isNew = true;
        }
//        6.之后从redis中删除验证码，防止用户重复提交
        redisTemplate.delete(key);
//        7.利用工具类JwtUtils将手机号和ID变成token
        String token = JwtUtils.createToken(user.getId(), phone);
//        8.将token作为key，user对象作为value存入Redis，设置1天有效
        String tokenKey = IctConstants.PREFIX_TOKEN + token;
        String userStr = JSON.toJSONString(dataUser); //将对象 转为 字符串
        redisTemplate.opsForValue().set(tokenKey, userStr, 1, TimeUnit.DAYS);
//        9.返回登录成功的数据（1.token 2.isNew）
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("isNew", isNew);
        return map;
    }

    @Override
    public PageResult<IctUserVO> getUserInfoList(IctUserDTO user) {
        // 首先根据角色条件查询出符合条件的用户
        List<Long> userIdList = null;
        if (!CollectionUtils.isEmpty(user.getRoleIds())) {
            LambdaQueryWrapper<IctUserRole> ictUserRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
            ictUserRoleLambdaQueryWrapper.in(IctUserRole::getRoleId, user.getRoleIds());
            List<IctUserRole> ictUserRoles = userRoleMapper.selectList(ictUserRoleLambdaQueryWrapper);
            userIdList = ictUserRoles.stream().map(IctUserRole::getUserId).collect(Collectors.toList());
        }

        Page<IctUser> ictUserPage = new Page<>(user.getPage(), user.getPageSize());

        LambdaQueryWrapper<IctUser> lqw = new LambdaQueryWrapper<>();
        lqw.in(!CollectionUtils.isEmpty(userIdList), IctUser::getId, userIdList);
        lqw.like(user.getUsername() != null, IctUser::getUsername, user.getUsername());
        lqw.like(user.getPhone() != null, IctUser::getPhone, user.getPhone());
        userMapper.selectPage(ictUserPage, lqw);
        List<IctUser> records = ictUserPage.getRecords();
        List<Long> userIds = records.stream().map(IctUser::getId).collect(Collectors.toList());

        // 查询出用户对应的角色名称
        List<IctUserVO> list = new ArrayList<>();
        LambdaQueryWrapper<IctUserRole> lqwIur = new LambdaQueryWrapper<>();
        lqwIur.in(IctUserRole::getUserId, userIds);
        List<IctUserRole> ictUserRoles = userRoleMapper.selectList(lqwIur);
        for (IctUser record : records) {
            IctUserVO ictUserVo = new IctUserVO();
            BeanUtils.copyProperties(record, ictUserVo);

            List<String> roleNamelist = new ArrayList<>();
            for (IctUserRole ictUserRole : ictUserRoles) {
                if (ictUserRole.getUserId().equals(record.getId())) {
                    roleNamelist.add(ictUserRole.getRoleName());
                }
            }
            ictUserVo.setRoleNames(roleNamelist);
            list.add(ictUserVo);
        }

        return new PageResult(user.getPage(), user.getPageSize(), ictUserPage.getTotal(), list);
    }

    @Override
    public IctUserVO getUserInfo(Long id) {
        IctUser ictUser = userMapper.selectById(id);
        IctUserVO ictUserVo = new IctUserVO();

        LambdaQueryWrapper<IctUserRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(IctUserRole::getUserId, id);
        List<IctUserRole> ictUserRoles = userRoleMapper.selectList(lqw);
        List<String> roleNames = ictUserRoles.stream().map(item -> item.getRoleName()).collect(Collectors.toList());

        ictUserVo.setRoleNames(roleNames);
        BeanUtils.copyProperties(ictUser, ictUserVo);
        return ictUserVo;
    }

    @Override
    public void deleteUser(Long id) {
        LambdaQueryWrapper<IctUserRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(IctUserRole::getUserId, id);
        userRoleMapper.delete(lqw);
        userMapper.deleteById(id);
    }

    @Override
    public void addOrUpdateUser(IctUserDTO user) {
        LambdaQueryWrapper<IctUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(IctUser::getUsername, user.getUsername());
        IctUser ictUser = userMapper.selectOne(lqw);

        if (ictUser == null) {
            // 新增用户逻辑
            userMapper.insert(user);
        } else {
            user.setId(ictUser.getId());
            userMapper.updateById(user);
        }

        // 角色分配
        if (!CollectionUtils.isEmpty(user.getRoleIds())) {
            IctRoleDTO ictRoleDTO = new IctRoleDTO();
            ictRoleDTO.setRoleIds(user.getRoleIds());
            roleService.setUserRoles(user.getId(), ictRoleDTO);
        }
    }

    @Override
    public void updateUserStatus(Long id, Integer status) {
        LambdaUpdateWrapper<IctUser> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(IctUser::getId, id);
        lambdaUpdateWrapper.set(IctUser::getStatus, status);
        userMapper.update(null, lambdaUpdateWrapper);
    }

}
